home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / 3DDEMO.ZIP / 3D / SOURCE / FILE.CPP < prev    next >
C/C++ Source or Header  |  1996-07-21  |  21KB  |  582 lines

  1. #include "file.hpp"
  2.  
  3. // Copyright (c) 1996 by Kerrigan Burgess, all rights reserved.
  4.  
  5. FILESYSTEMCLASS::FILESYSTEMCLASS(void)      // constructor.
  6. {
  7.  
  8. }
  9.  
  10. FILESYSTEMCLASS::~FILESYSTEMCLASS(void)     // destructor.
  11. {
  12.  
  13. }
  14.  
  15. int ObjectId=0;
  16.  
  17. int FILESYSTEMCLASS::CreateDataBase(MESHCLASS *Mesh, char *filename, int Status)
  18. {
  19.    char *type;
  20.  
  21.    type=strrchr(filename,'.');          // look for filename extension.
  22.    type++;                              // move pointer by 1.
  23.    
  24.    if (strncmp(type,"asc",3)==0)
  25.      LoadASC(Mesh,filename,Status);
  26.    else
  27.    if (strncmp(type,"gem",3)==0)
  28.      LoadGEM(Mesh,filename,Status);
  29.    else
  30.    if (strncmp(type,"geo",3)==0)
  31.      LoadGEO(Mesh,filename,Status);
  32.    else
  33.    {
  34.      Error("Unrecognized mesh format\n");
  35.    }
  36.  
  37.   return (ObjectId);
  38. }
  39.  
  40. void FILESYSTEMCLASS::LoadASC(MESHCLASS *Mesh, char *filename, int Status)
  41. {
  42.   FILE *fptr;
  43.   char buffer[200], name[20];
  44.   char *token;
  45.   int tindex=0,vertices,faces;
  46.   float fraction;
  47.   double integral;
  48.   int TextureMapped;
  49.  
  50.   fptr=fopen(filename,"r");
  51.   if (fptr==NULL)
  52.     Error("Couldn't find mesh\n");
  53.  
  54.   while ( !feof(fptr) )
  55.   {
  56.      fgets(buffer,200,fptr);
  57.      token=strtok(buffer," \t");
  58.  
  59.      if (!strcmp(token,"Named"))             // Look for Named object:
  60.      {
  61.         TextureMapped = FALSE;               // reset for this object.
  62.  
  63.         token=strtok(NULL," \t");            // junk.
  64.         token=strtok(NULL," \t");            
  65.         sscanf(token,"%s",name);
  66.  
  67.         fgets(buffer,200,fptr);
  68.         token=strtok(buffer," \t");
  69.  
  70.         while (strcmp(token,"Tri-mesh,"))      // if not Tri-mesh get next line.
  71.         {                                      // see if now its Tri-mesh.
  72.            fgets(buffer,200,fptr);
  73.            token=strtok(buffer," \t");
  74.         }
  75.  
  76.         token=strtok(NULL," \t");            // junk.
  77.         token=strtok(NULL," \t");            
  78.         sscanf(token,"%d",&vertices);
  79.         token=strtok(NULL," \t");            // junk.
  80.         token=strtok(NULL," \t");
  81.         sscanf(token,"%d",&faces);
  82.  
  83.         fgets(buffer,200,fptr);            // junk.
  84.         token=strtok(buffer," \t");            
  85.         while (strcmp(token,"Vertex"))    // loop until we get Vertex list:
  86.         {
  87.            fgets(buffer,200,fptr);
  88.            token=strtok(buffer," \t");
  89.         }
  90.             
  91.         int count;
  92.         OBJECTCLASS *Object = new OBJECTCLASS;     // creates a new object and adds to list.
  93.     if (Object==NULL)
  94.       Error("not enough memory\n");
  95.       
  96.         Object->numvertices=vertices;
  97.         Object->numpoly=faces;
  98.         Mesh->totalfaces+=faces;        // update total faces. Used to allocate MeshList.
  99.         strcpy(Object->name,name);
  100.         Object->ObjectID = ++ObjectId;
  101.     
  102.         int totalvertices;
  103.         totalvertices = 2*vertices;              // because we want to allocate enough
  104.                                                  // space to hold all vertices+avgnormals.
  105.         
  106.         Object->LocalCoord  = new POINT3D[totalvertices];  // allocate space for vertices.
  107.         if (Object->LocalCoord==NULL)
  108.       Error("not enough memory\n");
  109.         Object->CameraCoord = new POINT3D[totalvertices];
  110.     if (Object->CameraCoord==NULL)
  111.       Error("not enough memory\n");
  112.                                                          // zero everything out.
  113.                                                            
  114.         memset(Object->LocalCoord, '\0', sizeof(POINT3D)*totalvertices);
  115.         memset(Object->CameraCoord, '\0', sizeof(POINT3D)*totalvertices);
  116.         
  117.         for (count=0;count<vertices;count++)
  118.         {
  119.            fgets(buffer,200,fptr);       // read in next line.
  120.            token=strtok(buffer," \t");
  121.  
  122.            while (strcmp(token,"Vertex"))      // if not Tri-mesh get next line.
  123.            {
  124.               fgets(buffer,200,fptr);
  125.               token=strtok(buffer," \t");            
  126.            }
  127.  
  128.            token=strtok(NULL," \t");    // junk.
  129.            
  130.            token=strtok(NULL," \t");
  131.            if ( strlen(token) != 2 )
  132.            {
  133.               sscanf(&token[2],"%f",&(Object->LocalCoord[count].x));     
  134.            }
  135.            else
  136.            {
  137.               token=strtok(NULL," \t");  
  138.               sscanf(token,"%f",&(Object->LocalCoord[count].x));     
  139.            }
  140.  
  141.            token=strtok(NULL," \t");
  142.            if ( strlen(token) != 2 )
  143.            {
  144.               sscanf(&token[2],"%f",&(Object->LocalCoord[count].y));
  145.            }
  146.            else
  147.            {
  148.               token=strtok(NULL," \t");  
  149.               sscanf(token,"%f",&(Object->LocalCoord[count].y));     
  150.            }
  151.  
  152.            token=strtok(NULL," \t");
  153.            if ( strlen(token) != 2 )
  154.            {
  155.               sscanf(&token[2],"%f",&(Object->LocalCoord[count].z));     
  156.            }
  157.            else
  158.            {
  159.               token=strtok(NULL," \t");  
  160.               sscanf(token,"%f",&(Object->LocalCoord[count].z));     
  161.            }
  162.  
  163.            token=strtok(NULL," \t");
  164.            if (strncmp(token,"U:",2)==0)
  165.            {
  166.               TextureMapped=TRUE;
  167.                
  168.               if ( strlen(token) != 2 )
  169.               {
  170.                  sscanf(&token[2],"%f",&fraction);
  171.                  
  172.                  if (fraction<0)
  173.                    fraction = -fraction;
  174.                  if (fraction>1)
  175.                    fraction=modf((double)fraction,&integral);
  176.                      
  177.                  Object->CameraCoord[count].u = (int)255*fraction;
  178.               }
  179.               else
  180.               {
  181.                  token=strtok(NULL," \t");  
  182.                  sscanf(token,"%f",&fraction);
  183.                       
  184.                  if (fraction<0)
  185.                    fraction = -fraction;
  186.                  if (fraction>1)
  187.                    fraction=modf((double)fraction,&integral);
  188.  
  189.                  Object->CameraCoord[count].u = (int)255*fraction;
  190.               }
  191.  
  192.               token=strtok(NULL," \t");
  193.               
  194.               if ( strlen(token) != 2 )
  195.               {
  196.                  sscanf(&token[2],"%f",&fraction);
  197.                  
  198.                  if (fraction<0)
  199.                    fraction = -fraction;
  200.                  if (fraction>1)
  201.                    fraction=modf((double)fraction,&integral);
  202.  
  203.                  Object->CameraCoord[count].v = (int)255*fraction;
  204.               }
  205.               else
  206.               {
  207.                  token=strtok(NULL," \t");  
  208.                  sscanf(token,"%f",&fraction);
  209.                       
  210.                  if (fraction<0)
  211.                    fraction = -fraction;
  212.                  if (fraction>1)
  213.                    fraction=modf((double)fraction,&integral);
  214.                      
  215.                  Object->CameraCoord[count].v = (int)255*fraction;
  216.               }
  217.            }
  218.            
  219.         }  // end for loop (vertices).
  220.  
  221.         Object->FindCenter();               // translate vertices to center of rotation.
  222.         Object->ComputeRadius();            // used for object level culling, also scales object.
  223.     
  224.         Object->Polygon = new POLYGONCLASS[faces];  // allocate faces.
  225.     if (Object->Polygon==NULL)
  226.       Error("Not enough memory\n");
  227.       
  228.         memset(Object->Polygon, '\0', sizeof(POLYGONCLASS)*faces);  // zero out everything.
  229.  
  230.         POLYGONCLASS *Polygon;      // alias for This face.
  231.         int vertex0,vertex1,vertex2;
  232.            
  233.         struct tempstruct *polyinfo;   // used for precomputing avgnormals.
  234.         polyinfo = new struct tempstruct[faces];
  235.     if (polyinfo==NULL)
  236.       Error("not enough memory\n");      
  237.  
  238.         fgets(buffer,200,fptr);            // junk.
  239.         token=strtok(buffer," \t");
  240.         while (strcmp(token,"Face"))    // loop until we get Face list:
  241.         {
  242.            fgets(buffer,200,fptr);
  243.            token=strtok(buffer," \t");            
  244.         }
  245.  
  246.         int pindex;        
  247.         for (pindex=0;pindex<faces;pindex++)
  248.         {
  249.            fgets(buffer,200,fptr);       // read in next line.
  250.            token=strtok(buffer," \t");
  251.            
  252.            while (strcmp(token,"Face"))      // if not Face get next line.
  253.            {
  254.               fgets(buffer,200,fptr);
  255.               token=strtok(buffer," \t");            
  256.            }
  257.  
  258.            Polygon=&(Object->Polygon[pindex]);
  259.                     
  260.            token=strtok(NULL," \t");     // junk.
  261.  
  262.                                      // point directly to address of camera coords.
  263.            token=strtok(NULL," \t");
  264.            sscanf(&token[2],"%d",&vertex0);
  265.            Polygon->Vertex[0]=&(Object->CameraCoord[vertex0]);
  266.            
  267.            token=strtok(NULL," \t");            
  268.            sscanf(&token[2],"%d",&vertex1);
  269.            Polygon->Vertex[1]=&(Object->CameraCoord[vertex1]);
  270.  
  271.            token=strtok(NULL," \t");
  272.            sscanf(&token[2],"%d",&vertex2);
  273.            Polygon->Vertex[2]=&(Object->CameraCoord[vertex2]);
  274.  
  275.            Polygon->color =  252*(SHADES+1);      //  make it shades of white.
  276.            Polygon->shadowcolor = 0;              //  make it black.
  277.        
  278.            if (TextureMapped)
  279.        {            
  280.               Polygon->u0 = (Object->CameraCoord[vertex0]).u;
  281.               Polygon->v0 = (Object->CameraCoord[vertex0]).v;
  282.               Polygon->u1 = (Object->CameraCoord[vertex1]).u;
  283.               Polygon->v1 = (Object->CameraCoord[vertex1]).v;
  284.               Polygon->u2 = (Object->CameraCoord[vertex2]).u;
  285.               Polygon->v2 = (Object->CameraCoord[vertex2]).v;
  286.        } 
  287.        else                         // since it's not T-mapped, put in own coords.
  288.        {
  289.               Polygon->u0 = 3;
  290.               Polygon->v0 = 3;
  291.               Polygon->u1 = 127;
  292.               Polygon->v1 = 3;
  293.               Polygon->u2 = 127;
  294.               Polygon->v2 = 127;
  295.        }
  296.  
  297.            polyinfo[pindex].p0 = vertex0;   // save vertex indices for computing avgnormals.
  298.            polyinfo[pindex].p1 = vertex1;
  299.            polyinfo[pindex].p2 = vertex2;
  300.  
  301.            Object->ComputeNormalength(vertex0,vertex1,vertex2,Polygon);
  302.         }  // end while (faces).
  303.  
  304.        Object->PreComputeAvgNormal(polyinfo);
  305.        Object->numvertices=totalvertices;  // adjust vertices by 2x.
  306.        Mesh->Push(Object,Status);         // Add Object to linked list. Parent or Child?
  307.        delete polyinfo;                    // delete temporary structure for precomputing avgnormals.
  308.  
  309.      }   // end if (Named).
  310.   }  // end while (!eof).
  311. }
  312.  
  313. void FILESYSTEMCLASS::LoadGEM(MESHCLASS *Mesh, char *filename, int Status)
  314. {
  315.   FILE *fptr;
  316.   char buffer[200];
  317.   char *token;
  318.   int junk,count,vertices,faces,totalfaces=0;
  319.   int vertexcount;
  320.  
  321.   fptr=fopen(filename,"r");
  322.   if (fptr==NULL)
  323.     Error("Couldn't find mesh\n");
  324.  
  325.   if ( !feof(fptr) )
  326.   {
  327.      fscanf(fptr,"%d %d %d\n",&vertices,&faces,&junk);
  328.  
  329.      OBJECTCLASS *Object = new OBJECTCLASS;  // creates a new object and adds to list
  330.      if (Object==NULL)
  331.        Error("not enough memory\n");
  332.          
  333.      Object->numvertices=vertices;
  334.      Object->ObjectID = ++ObjectId;
  335.  
  336.      int totalvertices;
  337.      totalvertices = 2*vertices;             // because we want to allocate enough
  338.                                              // space to hold all vertices+avgnormals.
  339.         
  340.      Object->LocalCoord  = new POINT3D[totalvertices];  // allocate space for vertices.
  341.      if (Object->LocalCoord==NULL)
  342.        Error("not enough memory\n");
  343.      Object->CameraCoord = new POINT3D[totalvertices];
  344.      if (Object->CameraCoord==NULL)
  345.        Error("not enough memory\n");
  346.                                                          // zero everything out.
  347.                                                            
  348.      memset(Object->LocalCoord, '\0', sizeof(POINT3D)*totalvertices);
  349.      memset(Object->CameraCoord, '\0', sizeof(POINT3D)*totalvertices);
  350.  
  351.      for (count=0;count<vertices;count++)     // read in vertices.
  352.      {
  353.         fscanf( fptr,"%f %f %f\n",&(Object->LocalCoord[count].x),
  354.                               &(Object->LocalCoord[count].y),
  355.                         &(Object->LocalCoord[count].z) );
  356.      }
  357.  
  358.      Object->FindCenter();               // translate vertices so rotation is around the center.
  359.      Object->ComputeRadius();            // used for object level culling, also scales object.
  360.  
  361.      long offset,lines=0;                // save file pointer offset.
  362.      offset=ftell(fptr);                 // find out where we are in file.
  363.            
  364.      for (count=0;count<faces;count++)   // get actual count of faces. (some polys may have more than 3 vertices.)
  365.      {
  366.         fgets(buffer,200,fptr);      
  367.         token=strtok(buffer," \t");
  368.     sscanf(token,"%d",&vertexcount);
  369.        
  370.         totalfaces=totalfaces+1+(vertexcount-3);  // to split polygons with vertices > 3 into smaller polys.
  371.         lines++;
  372.      }
  373.      fseek(fptr,offset,SEEK_SET);     // return to original position.
  374.                   
  375.      Object->numpoly=totalfaces;
  376.      Mesh->totalfaces+=totalfaces;        // update total faces. Used to allocate MeshList.
  377.  
  378.      Object->Polygon = new POLYGONCLASS[totalfaces];  // allocate faces.
  379.      if (Object->Polygon==NULL)
  380.        Error("not enough memory\n");
  381.  
  382.      memset(Object->Polygon, '\0', sizeof(POLYGONCLASS)*totalfaces);  // zero out everything.
  383.  
  384.      POLYGONCLASS *Polygon;         // alias for This face.           
  385.      struct tempstruct *polyinfo;   // used for precomputing avgnormals.
  386.      polyinfo = new struct tempstruct[totalfaces];
  387.      if (polyinfo==NULL)
  388.        Error("not enough memory\n");
  389.  
  390.      int VertexId[20];              // should be enough.
  391.      
  392.      int pindex;
  393.      pindex=0;
  394.      
  395.      while (lines-- > 0)
  396.      {
  397.         fgets(buffer,200,fptr);      
  398.         token=strtok(buffer," \t");
  399.         sscanf(token,"%d",&vertexcount);
  400.  
  401.     for (count=vertexcount;count>0;count--)    // put in counterclockwise order.
  402.     {   
  403.            token=strtok(NULL," \t");
  404.            sscanf(token,"%d",&VertexId[count-1]);
  405.        VertexId[count-1]-=1;                   // index vertices for polys start at 0 not 1.
  406.     }
  407.     vertexcount=1+(vertexcount-3);           // this polygon has to be broken into vertexcount polys.
  408.  
  409.         for (count=0;count<vertexcount;count++)
  410.     {       
  411.            Polygon=&(Object->Polygon[pindex]);         // alias a pointer.
  412.  
  413.            Polygon->Vertex[0]=&(Object->CameraCoord[ VertexId[0]   ]);  // point directly to cameracoords
  414.            Polygon->Vertex[1]=&(Object->CameraCoord[ VertexId[count+1] ]);
  415.            Polygon->Vertex[2]=&(Object->CameraCoord[ VertexId[count+2] ]);
  416.                
  417.            Polygon->color = 252*(SHADES+1);       //  make it shades of white.
  418.            Polygon->shadowcolor = 0;              //  make it black.
  419.  
  420.            Polygon->u0 = 3;                       // supply own u,v coords.
  421.            Polygon->v0 = 3;
  422.            Polygon->u1 = 127;
  423.            Polygon->v1 = 3;
  424.            Polygon->u2 = 127;
  425.            Polygon->v2 = 127;
  426.  
  427.            polyinfo[pindex].p0 = VertexId[0];   // save vertex indices for computing avgnormals.
  428.            polyinfo[pindex].p1 = VertexId[count+1];
  429.            polyinfo[pindex].p2 = VertexId[count+2];
  430.  
  431.            Object->ComputeNormalength(VertexId[0], VertexId[count+1], VertexId[count+2], Polygon);
  432.        pindex++;                        // get next polygon.
  433.     }
  434.      }  // end while (faces).
  435.  
  436.    Object->PreComputeAvgNormal(polyinfo);
  437.    Object->numvertices=totalvertices;  // adjust vertices by 2x.
  438.    Mesh->Push(Object,Status);                // Add Object to linked list. Parent or Child?
  439.    delete polyinfo;                    // delete temporary structure for precomputing avgnormals.
  440.  
  441.   }  // end if (!eof).
  442. }
  443.  
  444. void FILESYSTEMCLASS::LoadGEO(MESHCLASS *Mesh, char *filename, int Status)
  445. {
  446.   FILE *fptr;
  447.   char buffer[200];
  448.   char *token;
  449.   int count,vertices,totalfaces=0;
  450.   int vertexcount;
  451.   
  452.   fptr=fopen(filename,"r");
  453.   if (fptr==NULL)
  454.     Error("Couldn't find mesh\n");
  455.  
  456.   if ( !feof(fptr) )
  457.   {
  458.      fgets(buffer,200,fptr);            // read header.
  459.  
  460.      fscanf(fptr,"%d\n",&vertices);     // num of vertices.
  461.      
  462.      OBJECTCLASS *Object = new OBJECTCLASS;  // creates a new object and adds to list
  463.      if (Object==NULL)
  464.        Error("not enough memory\n");
  465.     
  466.      Object->numvertices=vertices;
  467.      Object->ObjectID = ++ObjectId;
  468.  
  469.      int totalvertices;
  470.      totalvertices = 2*vertices;             // because we want to allocate enough
  471.                                              // space to hold all vertices+avgnormals.
  472.  
  473.      Object->LocalCoord  = new POINT3D[totalvertices];  // allocate space for vertices.
  474.      if (Object->LocalCoord==NULL)
  475.        Error("not enough memory\n");
  476.      Object->CameraCoord = new POINT3D[totalvertices];
  477.      if (Object->CameraCoord==NULL)
  478.        Error("not enough memory\n");
  479.                                                                 // zero everything out.
  480.                                                            
  481.      memset(Object->LocalCoord, '\0', sizeof(POINT3D)*totalvertices);
  482.      memset(Object->CameraCoord, '\0', sizeof(POINT3D)*totalvertices);
  483.  
  484.      for (count=0;count<vertices;count++)     // read in vertices.
  485.      {
  486.         fscanf( fptr,"%f %f %f\n",&(Object->LocalCoord[count].x),
  487.                             &(Object->LocalCoord[count].y),
  488.                     &(Object->LocalCoord[count].z) );
  489.      }
  490.  
  491.      Object->FindCenter();               // translate vertices so rotation is around the center.
  492.      Object->ComputeRadius();            // used for object level culling, also scales object.
  493.  
  494.      long offset,lines=0;                // save file pointer offset.
  495.      offset=ftell(fptr);                 // find out where we are in file.
  496.  
  497.      for (;;)
  498.      {
  499.         if (fgets(buffer,200,fptr) == NULL)
  500.       break;                         // reached EOF.
  501.     else
  502.     {
  503.       token=strtok(buffer," \t");
  504.       sscanf(token,"%d",&vertexcount);
  505.       if (vertexcount>2)         // only add to total faces if vertices are greater than 2.
  506.             totalfaces=totalfaces+1+(vertexcount-3);  // to split polygons with vertices > 3 into smaller polys.
  507.       lines++;
  508.     }
  509.      }
  510.      fseek(fptr,offset,SEEK_SET);     // return to original position.
  511.                   
  512.      Object->numpoly=totalfaces;
  513.      Mesh->totalfaces+=totalfaces;        // update total faces. Used to allocate MeshList.
  514.  
  515.      Object->Polygon = new POLYGONCLASS[totalfaces];  // allocate faces.
  516.      if (Object->Polygon==NULL)
  517.        Error("not enough memory\n");
  518.  
  519.      memset(Object->Polygon, '\0', sizeof(POLYGONCLASS)*totalfaces);  // zero out everything.
  520.  
  521.      POLYGONCLASS *Polygon;         // alias for This face.           
  522.      struct tempstruct *polyinfo;   // used for precomputing avgnormals.
  523.      polyinfo = new struct tempstruct[totalfaces];
  524.      if (polyinfo==NULL)
  525.        Error("not enough memory\n");
  526.        
  527.      int VertexId[20];              // should be enough.
  528.      
  529.      int pindex;
  530.      pindex=0;
  531.      
  532.      while (lines-- > 0)     
  533.      {
  534.         fgets(buffer,200,fptr);       // read in next line.
  535.  
  536.         token=strtok(buffer," \t");
  537.         sscanf(token,"%d",&vertexcount);
  538.         if (vertexcount<3)            // if vertices don't makeup a complete poly, continue.
  539.       continue;
  540.       
  541.     for (count=0;count<vertexcount;count++)
  542.     {   
  543.            token=strtok(NULL," \t");
  544.            sscanf(token,"%d",&VertexId[count]);
  545.     }
  546.     vertexcount=1+(vertexcount-3);           // this polygon has to be broken into vertexcount polys.
  547.  
  548.         for (count=0;count<vertexcount;count++)
  549.     {       
  550.            Polygon=&(Object->Polygon[pindex]);         // alias a pointer.
  551.  
  552.            Polygon->Vertex[0]=&(Object->CameraCoord[ VertexId[0]   ]);  // point directly to cameracoords
  553.            Polygon->Vertex[1]=&(Object->CameraCoord[ VertexId[count+1] ]);
  554.            Polygon->Vertex[2]=&(Object->CameraCoord[ VertexId[count+2] ]);
  555.                
  556.            Polygon->color = 252*(SHADES+1);       //  make it shades of white.
  557.            Polygon->shadowcolor = 0;              //  make it black.
  558.  
  559.            Polygon->u0 = 3;                       // supply own u,v coords.
  560.            Polygon->v0 = 3;
  561.            Polygon->u1 = 127;
  562.            Polygon->v1 = 3;
  563.            Polygon->u2 = 127;
  564.            Polygon->v2 = 127;
  565.  
  566.            polyinfo[pindex].p0 = VertexId[0];   // save vertex indices for computing avgnormals.
  567.            polyinfo[pindex].p1 = VertexId[count+1];
  568.            polyinfo[pindex].p2 = VertexId[count+2];
  569.  
  570.            Object->ComputeNormalength(VertexId[0], VertexId[count+1], VertexId[count+2], Polygon);
  571.        pindex++;                        // get next polygon.
  572.     }
  573.      }  // end while (faces).
  574.  
  575.    Object->PreComputeAvgNormal(polyinfo);
  576.    Object->numvertices=totalvertices;  // adjust vertices by 2x.
  577.    Mesh->Push(Object,Status);                // Add Object to linked list. Parent or Child?
  578.    delete polyinfo;                    // delete temporary structure for precomputing avgnormals.
  579.  
  580.   }  // end if (!eof).
  581. }
  582.